import numpy
import time
import math
import pandas as pd

threshold = 0.1 # 阈值


class dataClass:
    pass


class AAndP:
    pass


def updateList(input_list):
    """使列表中的每一个元素都加上前一个元素"""
    pre = 0
    out_list = []
    for item in input_list:
        item = float(item) + float(pre)
        out_list.append(item)
        pre = item

    return out_list

def dataInput(filename):
    """读取文件并修改列名，将最后一列名改成tag"""
    df = pd.read_excel('./data/' + filename, 'Sheet1', header=None)
    df.columns = df.columns.map(lambda x: 'a' + str(x))
    ret = list(df.columns)
    ret[-1] = 'tag'
    df.columns = ret
    return df


def readCsv(filename):
    df = pd.read_csv(filename)
    return df


def dataPreprocess(df):
    df.sample(frac=1).reset_index(drop=True)
    data = dataClass()
    segment_length = math.ceil(df.shape[0] / 10)  # 向上取整不拉数据
    df_half_length = segment_length * 5
    #  数据五等份
    data.u0 = df.iloc[:df_half_length]
    data.u1 = df.iloc[df_half_length:segment_length * 6]
    data.u2 = df.iloc[df_half_length:segment_length * 7]
    data.u3 = df.iloc[df_half_length:segment_length * 8]
    data.u4 = df.iloc[df_half_length:segment_length * 9]
    data.u5 = df.iloc[df_half_length:segment_length * 10]
    return data


def consOfSimple(simple, data, features):
    """计算某一特定样本关于指定特征的一致度"""
    count = 0
    df = data.copy()
    for feature in features:
        try:
            key = int(simple[feature])
        except ValueError:
            key = simple[feature]
            print('不是整数')
        df = df[df[feature].isin([key])]
    df_group = df.groupby('tag')
    # df_list = list(df.index)
    # data = data.drop(df_list)
    if len(df_group.count().index) == 1:
        return True
    else:
        return False


def consOfU(u, features):
    """数据集U关于给入的特征值的一致度计算"""
    count_u = u.copy()
    cons = 0
    # it = iter(count_u.iloc)
    # while True:
    #     try:
    #         if consOfSimple(next(it), count_u, features):
    #             cons += 1
    #     except StopIteration:
    #         break
    # # print("该数据集的一致度为：", cons)
    pass_set = {}
    for simple in count_u.iloc:
        if consOfSimple(simple, count_u, features):
            cons += 1
    return cons / u.shape[0]


def step2(u, cons_a, features_list):
    cons_u_p = 0
    P = []
    while (cons_a - cons_u_p) >= threshold:
        max_cons = 0
        max_index = ""
        for feature in features_list:
            tempP = P.copy()
            tempP.append(feature)
            # print(tempP)
            tempCons = consOfU(u, tempP)
            # print("P U", feature, "=", tempCons)
            if max_cons <= tempCons:
                max_cons = tempCons
                max_index = feature
        P.append(max_index)
        # print("添加：", max_index)
        features_list.remove(max_index)
        cons_u_p = max_cons
        print("现在的cons值是:", cons_u_p)

    print('输出的P是', P)
    return [P, cons_u_p]


def calculateConsAndP(u, times):
    result = AAndP()
    features_list = list(u.columns)
    features_list.pop()
    t = time.time()
    result.consA = consOfU(u, features_list)
    print("consA的值是"+str(result.consA))
    print(f"==计算consA耗时：{time.time() - t:.4f}")
    step2_result = step2(u, result.consA, features_list)
    result.P = step2_result[0]
    result.consP = step2_result[1]
    times.append(f'{time.time() - t:.4f} ')
    print(f"==step2耗时：{time.time() - t:.4f}")
    return result


# U_good = pd.DataFrame()
# U0 = pd.read_csv('newData.csv')


def filterAlgorithm(old_data, new_data):
    filtered_data = pd.DataFrame()
    for newSimple in new_data.iloc:
        flag = 0
        for oldSimple in old_data.iloc:
            for feature in list(old_data.columns):
                if newSimple[feature] == oldSimple[feature]:
                    continue
                else:
                    flag = 1
                    break
            if flag == 0:
                break
        if flag == 1:
            filtered_data = filtered_data.append(newSimple, ignore_index=True)
    return filtered_data


def countCupConsWithOldUnknown(u, u0, features):
    cons_ua = consOfU(u, features)
    print("旧数据的一致度是：", cons_ua)
    cons_u_good_a = consOfU(u0, features)
    print("新数据的一致度是：", cons_u_good_a)
    return (u.shape[0] * cons_ua + u0.shape[0] * cons_u_good_a) / (u.shape[0] + u0.shape[0])


def countCupConsWithOldKnown(old_length, cons_old, u_new, features):
    cons_new = consOfU(u_new, features)
    print("新数据关于"+str(features[:5])+"的一致度是：", cons_new)
    return (old_length * cons_old + u_new.shape[0] * cons_new) / (old_length + u_new.shape[0])


def increment(old_df, new_df, last_data_result, times):
    result = AAndP()
    c_features = list(old_df.columns)
    c_features.pop()
    b_features = []
    t = time.time()
    filtered_df = filterAlgorithm(old_df, new_df)
    result.new_df = old_df.append(filtered_df, True)
    cons_cup_of_c = countCupConsWithOldKnown(old_df.shape[0], last_data_result.consA, filtered_df, c_features)
    cons_cup_of_p = countCupConsWithOldKnown(old_df.shape[0], last_data_result.consP, filtered_df, last_data_result.P)
    print('关于C特征集的一致度：', cons_cup_of_c)
    print('关于P特征集的一致度：', cons_cup_of_p)
    if abs(cons_cup_of_p - cons_cup_of_c) < 0.1:
        print('不需要添加特征')
    else:
        print("==========开始增量")
        f_features = list(set(c_features)-set(last_data_result.P))
        while abs(cons_cup_of_p - cons_cup_of_c) >= 0.1:
            max_cons = 0
            max_index = ""
            for feature in f_features:
                temp_p = last_data_result.P
                temp_p = temp_p + b_features
                temp_p.append(feature)
                print(temp_p)
                temp_cons = countCupConsWithOldUnknown(old_df, filtered_df, temp_p)
                print("P U B U ", feature, "=", temp_cons)
                if max_cons < temp_cons:
                    max_cons = temp_cons
                    max_index = feature
            b_features.append(max_index)
            print("添加：", max_index)
            f_features.remove(max_index)
            cons_cup_of_p = max_cons
            print("现在cons_U_p的值是：", cons_cup_of_p)
        print('现在P是：', last_data_result.P+b_features)

        print('****************现在开始删除冗余数据')
        while 1:
            min_flag = 0
            min_index = ""
            for feature in last_data_result.P:
                temp_p = last_data_result.P.copy()
                temp_p = temp_p + b_features
                temp_p.remove(feature)
                temp_cons = countCupConsWithOldUnknown(old_df, filtered_df, temp_p)
                print("P - ", feature, "=", temp_cons)
                if abs(cons_cup_of_c - temp_cons) <= threshold/2:
                    last_data_result.P.remove(feature)
                    print("删除特征值：", feature)
                    cons_cup_of_p = temp_cons
                    min_flag = 1
            if min_flag == 0:
                print("没有特征值可删")
                break
    p_features = last_data_result.P + b_features
    print(p_features)
    times.append(f'{time.time() - t:.4f} ')

    result.consA = cons_cup_of_c
    result.consP = cons_cup_of_p
    result.P = p_features
    return result
